import 'dart:io';

import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:flutter/foundation.dart';
import 'package:http_parser/http_parser.dart';
import 'package:ylm_ui_kit/ylm_ui_kit.dart';

import 'common_net.dart';
import 'common_net_interceptor.dart';

///提供网络请求能力
class LinkNetSkeleton extends CommonNetSkeleton {
  LinkNetSkeleton({String? ip, String? port})
      : _ip = ip,
        _port = port;

  late Dio dio;
  final String? _ip, _port; //代理
  late CommonNetBuilder _commonNetBuilder;

  @override
  Future init(CommonNetBuilder commonNetBuilder) async {
    _commonNetBuilder = commonNetBuilder;
    dio = Dio(BaseOptions(
      baseUrl: commonNetBuilder.getBaseUrl(),
      connectTimeout: const Duration(seconds: 30),
      receiveTimeout: const Duration(seconds: 30),
      headers: await commonNetBuilder.initHeaders(),
    ));
    if (kDebugMode) {
      dio.interceptors.addAll([
        LogInterceptor(
          request: false,
          requestBody: true,
          responseHeader: false,
          responseBody: true,
          logPrint: (log) {
            Log.log(log.toString());
          },
        ),
        LinkInterceptToCurl(printOnSuccess: true),
      ]);

      (dio.httpClientAdapter as IOHttpClientAdapter).onHttpClientCreate = (client) {
        client.findProxy = (uri) {
          if (_ip == null) return "DIRECT";
          return "PROXY $_ip:$_port";
        };

        ///校验证书
        client.badCertificateCallback = (X509Certificate cert, String host, int port) {
          return true; //证书一致，则允许发送数据
        };
      };
    }
  }

  @override
  Future release() async => dio.close(force: true);

  void setDioOptions({String? baseUrl, String? contentType}) {
    dio.options.baseUrl = baseUrl.notEmpty ? baseUrl! : _commonNetBuilder.getBaseUrl();
    if (contentType.notEmpty) dio.options.contentType = contentType;
  }

  @override
  Future<dynamic> commonGet(CommonApi api, {String? baseUrl, String? contentType}) async {
    setDioOptions(baseUrl: baseUrl, contentType: contentType);
    Response response = await dio.get(api.api, queryParameters: api.params);
    return response.data;
  }

  @override
  Future<dynamic> commonPost(CommonApi api, {String? baseUrl, String? contentType}) async {
    setDioOptions(baseUrl: baseUrl, contentType: contentType);
    Response response = await dio.post(api.api, data: api.params);
    return response.data;
  }

  @override
  Future<dynamic> commonUpload(CommonUploadApi api,
      {CommonProgress? progress, String? baseUrl, String? contentType}) async {
    setDioOptions(baseUrl: baseUrl, contentType: contentType);
    var lists = <MultipartFile>[];
    MultipartFile mf;
    String end;
    String temp;
    for (int i = 0; i < api.filePaths.length; i++) {
      temp = api.filePaths[i];
      end = temp.split('.').last;
      mf = await MultipartFile.fromFile(
        temp,
        filename: 'file${i}_${DateTime.now()}.$end',
        contentType: MediaType(api.mediaType, end),
      );
      lists.add(mf);
    }
    api.params.addAll({api.uploadFileParamsName: lists});
    var formData = FormData.fromMap(api.params);
    Response response;
    response = await dio.post(api.api, data: formData, onSendProgress: progress);
    return response.data;
  }

  @override
  Future<dynamic> commonDownload(CommonDownloadApi api,
      {CommonProgress? progress, String? baseUrl, String? contentType}) async {
    setDioOptions(baseUrl: baseUrl, contentType: contentType);
    Response response = await dio.download(
      api.api,
      api.saveFilePath,
      onReceiveProgress: progress,
      options: Options(receiveTimeout: const Duration(hours: 1)),
    );
    return response.data;
  }

  @override
  Future<dynamic> unSupport(dynamic api, {CommonProgress? progress, String? baseUrl}) async {
    return "";
  }

  @override
  CommonNetError reduceError(e) {
    if (e is DioError) {
      if (e.type == DioErrorType.connectionTimeout || e.type == DioErrorType.receiveTimeout) {
        return CommonNetError.connectTimeout;
      }
      if (e.type == DioErrorType.sendTimeout) return CommonNetError.sendTimeout;
      if (e.type == DioErrorType.cancel) return CommonNetError.cancel;
      if (e.type == DioErrorType.unknown) {
        if (e.message?.contains('Failed host lookup') ?? false || (e.message?.contains('OS Error') ?? false)) {
          return CommonNetError.netError;
        }
      }
    }
    return CommonNetError.other;
  }

  @override
  Future refreshHeader() async {
    dio.options.headers = await _commonNetBuilder.initHeaders();
  }
}
